/**
 * @file database_manager.cpp
 * @brief 数据库管理器实现
 */

#include "database_manager.h"
#include "sysconfig.h"
#include "logger.hpp"
#include <ctime>
#include <iomanip>
#include <sstream>

DatabaseManager& DatabaseManager::getInstance() 
{
    static DatabaseManager instance;
    return instance;
}

DatabaseManager::~DatabaseManager() 
{
    cleanup();
}

/**
 * @brief 初始化数据库
 */
bool DatabaseManager::init() 
{
    std::lock_guard<std::mutex> lock(mutex_);
    
    // 打开数据库连接
    int result = sqlite3_open(Config::getDatabasePath().c_str(), &db_);
    if (result != SQLITE_OK) 
    {
        Log::GetLogger("asynclogger")->Warn("打开数据库失败: %s", sqlite3_errmsg(db_));
        return false;
    }
    
    // 启用外键约束
    sqlite3_exec(db_, "PRAGMA foreign_keys = ON;", nullptr, nullptr, nullptr);
    
    // 设置WAL模式以提高并发性能
    sqlite3_exec(db_, "PRAGMA journal_mode = WAL;", nullptr, nullptr, nullptr);
    
    // 创建数据表
    if (!createTables())
    {
        Log::GetLogger("asynclogger")->Warn("创建数据表失败");
        return false;
    }
    
    // 准备SQL语句
    if (!prepareStatements()) 
    {
        Log::GetLogger("asynclogger")->Warn("准备SQL语句失败");
        return false;
    }
    
    Log::GetLogger("asynclogger")->Info("数据库初始化成功");
    return true;
}

/**
 * @brief 清理资源
 */
void DatabaseManager::cleanup() 
{
    std::lock_guard<std::mutex> lock(mutex_);
    
    // 清理预编译语句
    if (stmt_insert_) 
    {
        sqlite3_finalize(stmt_insert_);
        stmt_insert_ = nullptr;
    }
    if (stmt_select_by_id_) 
    {
        sqlite3_finalize(stmt_select_by_id_);
        stmt_select_by_id_ = nullptr;
    }
    if (stmt_select_by_hash_) 
    {
        sqlite3_finalize(stmt_select_by_hash_);
        stmt_select_by_hash_ = nullptr;
    }
    if (stmt_update_count_) 
    {
        sqlite3_finalize(stmt_update_count_);
        stmt_update_count_ = nullptr;
    }
    if (stmt_check_id_) 
    {
        sqlite3_finalize(stmt_check_id_);
        stmt_check_id_ = nullptr;
    }
    if (stmt_check_hash_) 
    {
        sqlite3_finalize(stmt_check_hash_);
        stmt_check_hash_ = nullptr;
    }
    
    // 关闭数据库连接
    if (db_) 
    {
        sqlite3_close(db_);
        db_ = nullptr;
    }
}

/**
 * @brief 创建数据表
 */
bool DatabaseManager::createTables() 
{
    const char* sql = R"(
        CREATE TABLE IF NOT EXISTS file_mapping (
            id VARCHAR(6) PRIMARY KEY,
            hash VARCHAR(64) UNIQUE NOT NULL,
            filename VARCHAR(255) NOT NULL,
            filesize BIGINT NOT NULL,
            mime_type VARCHAR(100),
            upload_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            download_count INT DEFAULT 0
        );
        
        CREATE INDEX IF NOT EXISTS idx_hash ON file_mapping(hash);
        CREATE INDEX IF NOT EXISTS idx_upload_time ON file_mapping(upload_time);
    )";
    
    char* error_msg = nullptr;
    int result = sqlite3_exec(db_, sql, nullptr, nullptr, &error_msg);
    
    if (result != SQLITE_OK) 
    {
        Log::GetLogger("asynclogger")->Info("创建数据表失败: %s", error_msg);
        sqlite3_free(error_msg);
        return false;
    }
    
    return true;
}

/**
 * @brief 准备SQL语句
 */
bool DatabaseManager::prepareStatements() 
{
    // 插入语句
    const char* insert_sql = 
        "INSERT INTO file_mapping (id, hash, filename, filesize, mime_type, upload_time) "
        "VALUES (?, ?, ?, ?, ?, ?)";
    if (sqlite3_prepare_v2(db_, insert_sql, -1, &stmt_insert_, nullptr) != SQLITE_OK) 
    {
        Log::GetLogger("asynclogger")->Info("准备插入语句失败: %s", sqlite3_errmsg(db_));
        return false;
    }
    
    // 按ID查询语句
    const char* select_by_id_sql = 
        "SELECT id, hash, filename, filesize, mime_type, upload_time, download_count "
        "FROM file_mapping WHERE id = ?";
    if (sqlite3_prepare_v2(db_, select_by_id_sql, -1, &stmt_select_by_id_, nullptr) != SQLITE_OK) 
    {
        Log::GetLogger("asynclogger")->Info("准备ID查询语句失败: %s", sqlite3_errmsg(db_));
        return false;
    }
    
    // 按哈希查询语句
    const char* select_by_hash_sql = 
        "SELECT id, hash, filename, filesize, mime_type, upload_time, download_count "
        "FROM file_mapping WHERE hash = ?";
    if (sqlite3_prepare_v2(db_, select_by_hash_sql, -1, &stmt_select_by_hash_, nullptr) != SQLITE_OK) 
    {
        Log::GetLogger("asynclogger")->Info("准备哈希查询语句失败: %s", sqlite3_errmsg(db_));
        return false;
    }
    
    // 更新下载次数语句
    const char* update_count_sql = 
        "UPDATE file_mapping SET download_count = download_count + 1 WHERE id = ?";
    if (sqlite3_prepare_v2(db_, update_count_sql, -1, &stmt_update_count_, nullptr) != SQLITE_OK) 
    {
        Log::GetLogger("asynclogger")->Info("准备更新语句失败: %s", sqlite3_errmsg(db_));
        return false;
    }
    
    // 检查ID存在语句
    const char* check_id_sql = "SELECT 1 FROM file_mapping WHERE id = ?";
    if (sqlite3_prepare_v2(db_, check_id_sql, -1, &stmt_check_id_, nullptr) != SQLITE_OK) 
    {
        Log::GetLogger("asynclogger")->Info("准备ID检查语句失败: %s", sqlite3_errmsg(db_));
        return false;
    }
    
    // 检查哈希存在语句
    const char* check_hash_sql = "SELECT 1 FROM file_mapping WHERE hash = ?";
    if (sqlite3_prepare_v2(db_, check_hash_sql, -1, &stmt_check_hash_, nullptr) != SQLITE_OK) 
    {
        Log::GetLogger("asynclogger")->Info("准备哈希检查语句失败: %s", sqlite3_errmsg(db_));
        return false;
    }
    
    return true;
}

/**
 * @brief 插入文件信息
 */
bool DatabaseManager::insertFile(const FileInfo& file_info) 
{
    std::lock_guard<std::mutex> lock(mutex_);
    
    // 绑定参数
    sqlite3_bind_text(stmt_insert_, 1, file_info.id.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt_insert_, 2, file_info.hash.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt_insert_, 3, file_info.filename.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_int64(stmt_insert_, 4, file_info.filesize);
    sqlite3_bind_text(stmt_insert_, 5, file_info.mime_type.c_str(), -1, SQLITE_STATIC);
    sqlite3_bind_text(stmt_insert_, 6, file_info.upload_time.c_str(), -1, SQLITE_STATIC);
    
    // 执行语句
    int result = sqlite3_step(stmt_insert_);
    sqlite3_reset(stmt_insert_);
    
    if (result != SQLITE_DONE) 
    {
        Log::GetLogger("asynclogger")->Info("插入文件信息失败: %s", sqlite3_errmsg(db_));
        return false;
    }
    
    return true;
}

/**
 * @brief 根据ID查询文件信息
 */
bool DatabaseManager::getFileById(const std::string& id, FileInfo& file_info) 
{
    std::lock_guard<std::mutex> lock(mutex_);
    
    // 绑定参数
    sqlite3_bind_text(stmt_select_by_id_, 1, id.c_str(), -1, SQLITE_STATIC);
    
    // 执行查询
    int result = sqlite3_step(stmt_select_by_id_);
    
    if (result == SQLITE_ROW) 
    {
        // 获取查询结果
        file_info.id = (char*)sqlite3_column_text(stmt_select_by_id_, 0);
        file_info.hash = (char*)sqlite3_column_text(stmt_select_by_id_, 1);
        file_info.filename = (char*)sqlite3_column_text(stmt_select_by_id_, 2);
        file_info.filesize = sqlite3_column_int64(stmt_select_by_id_, 3);
        file_info.mime_type = (char*)sqlite3_column_text(stmt_select_by_id_, 4);
        file_info.upload_time = (char*)sqlite3_column_text(stmt_select_by_id_, 5);
        file_info.download_count = sqlite3_column_int(stmt_select_by_id_, 6);
        
        sqlite3_reset(stmt_select_by_id_);
        return true;
    }
    
    sqlite3_reset(stmt_select_by_id_);
    return false;
}

/**
 * @brief 根据哈希值查询文件信息
 */
bool DatabaseManager::getFileByHash(const std::string& hash, FileInfo& file_info) 
{
    std::lock_guard<std::mutex> lock(mutex_);
    
    // 绑定参数
    sqlite3_bind_text(stmt_select_by_hash_, 1, hash.c_str(), -1, SQLITE_STATIC);
    
    // 执行查询
    int result = sqlite3_step(stmt_select_by_hash_);
    
    if (result == SQLITE_ROW) 
    {
        // 获取查询结果
        file_info.id = (char*)sqlite3_column_text(stmt_select_by_hash_, 0);
        file_info.hash = (char*)sqlite3_column_text(stmt_select_by_hash_, 1);
        file_info.filename = (char*)sqlite3_column_text(stmt_select_by_hash_, 2);
        file_info.filesize = sqlite3_column_int64(stmt_select_by_hash_, 3);
        file_info.mime_type = (char*)sqlite3_column_text(stmt_select_by_hash_, 4);
        file_info.upload_time = (char*)sqlite3_column_text(stmt_select_by_hash_, 5);
        file_info.download_count = sqlite3_column_int(stmt_select_by_hash_, 6);
        
        sqlite3_reset(stmt_select_by_hash_);
        return true;
    }
    
    sqlite3_reset(stmt_select_by_hash_);
    return false;
}

/**
 * @brief 更新下载次数
 */
bool DatabaseManager::updateDownloadCount(const std::string& id) 
{
    std::lock_guard<std::mutex> lock(mutex_);
    
    // 绑定参数
    sqlite3_bind_text(stmt_update_count_, 1, id.c_str(), -1, SQLITE_STATIC);
    
    // 执行更新
    int result = sqlite3_step(stmt_update_count_);
    sqlite3_reset(stmt_update_count_);
    
    return (result == SQLITE_DONE);
}

/**
 * @brief 检查ID是否存在
 */
bool DatabaseManager::isIdExists(const std::string& id) 
{
    std::lock_guard<std::mutex> lock(mutex_);
    
    // 绑定参数
    sqlite3_bind_text(stmt_check_id_, 1, id.c_str(), -1, SQLITE_STATIC);
    
    // 执行查询
    int result = sqlite3_step(stmt_check_id_);
    bool exists = (result == SQLITE_ROW);
    
    sqlite3_reset(stmt_check_id_);
    return exists;
}

/**
 * @brief 检查哈希值是否存在
 */
bool DatabaseManager::isHashExists(const std::string& hash) 
{
    std::lock_guard<std::mutex> lock(mutex_);
    
    // 绑定参数
    sqlite3_bind_text(stmt_check_hash_, 1, hash.c_str(), -1, SQLITE_STATIC);
    
    // 执行查询
    int result = sqlite3_step(stmt_check_hash_);
    bool exists = (result == SQLITE_ROW);
    
    sqlite3_reset(stmt_check_hash_);
    return exists;
} 